////////////////////////////////////////////////////////////////////////////////////////////////////
/// @file   CollabRCBotUnitTests\TestMemberVariableTreeNode.h
///
/// @brief  Defines the test suite for CollabRC::Bot::AI::MemberVariableTreeNode
////////////////////////////////////////////////////////////////////////////////////////////////////

#include <cxxtest/TestSuite.h>
#include "../CollabRCBot/MemberVariableTreeNode.h"
#include "../CollabRCBot/WordChoiceGene.h"
#include "RandomMock.h"


class TestMemberVariableTreeNode : public CxxTest::TestSuite
{
private:
    /**
     * Implementation of a CollabRC::Bot::WordSet which acts as an empty
     * word set
     * @version $Id$
     * @author Matthew P. Del Buono
     */
    class EmptySet : public CollabRC::Bot::WordSet
    {
    public:
        virtual void Reset() const { };
        virtual bool NextWord() const { return false; };
        virtual const QString& GetCurrentWord() const { CollabRC::Bot::NoCurrentElementException ex; throw ex; };
        virtual unsigned int GetCurrentWordCount() const { CollabRC::Bot::NoCurrentElementException ex; throw ex; };
    } emptySet;

    class MockWordChoiceGene : public CollabRC::Bot::AI::WordChoiceGene
    {
    public:
        MockWordChoiceGene(const CollabRC::Bot::WordSet& wordSet):WordChoiceGene(wordSet)
        {
        }
        float value;
    };

public:
    void TestCompute()
    {
        MinRandom mockRng;      // For "CreateDefaultAlgorithm()"

        MockWordChoiceGene gene(emptySet);
        gene.value = 4.5f;
        CollabRC::Bot::AI::MemberVariableTreeNode<MockWordChoiceGene, float> node(gene, &MockWordChoiceGene::value);
        TS_ASSERT_EQUALS(node.Compute(), 4.5f);

        // Try changing the value
        gene.value = 5.0f;
        TS_ASSERT_EQUALS(node.Compute(), 5.0f);

        // Try changing the object
        MockWordChoiceGene gene2(emptySet);
        gene2.value = 6.0f;
        TS_ASSERT_THROWS_NOTHING(node.SetObject(gene2));
        TS_ASSERT_EQUALS(node.Compute(), 6.0f);
    }

    void TestGetBranchDepth()
    {
        MinRandom rand;
        MockWordChoiceGene gene(emptySet);
        CollabRC::Bot::AI::MemberVariableTreeNode<MockWordChoiceGene, float> node(gene, &MockWordChoiceGene::value);
        TS_ASSERT_EQUALS(node.GetBranchDepth(), 1);
    }

    void TestGetRandomBranch()
    {
        MinRandom rand;
        MockWordChoiceGene gene(emptySet);
        CollabRC::Bot::AI::MemberVariableTreeNode<MockWordChoiceGene, float> node(gene, &MockWordChoiceGene::value);

        // Should always return itself -- there are no other branches
        TS_ASSERT(&(node.GetRandomBranch(0)) == &node);
        TS_ASSERT(&(node.GetRandomBranch(1)) == &node);
        TS_ASSERT(&(node.GetRandomBranch(2)) == &node);
    }

    void TestMutate()
    {
        MinRandom rand;
        MockWordChoiceGene gene(emptySet);
        CollabRC::Bot::AI::MemberVariableTreeNode<MockWordChoiceGene, float> node(gene, &MockWordChoiceGene::value);
        TS_ASSERT_THROWS(node.Mutate(0), const CollabRC::Bot::AI::IllegalMutationException&);
        TS_ASSERT_THROWS(node.Mutate(1), const CollabRC::Bot::AI::IllegalMutationException&);
    }

    void TestCreateDefaultAlgorithm()
    {
        TS_WARN("Test Not Yet Implemented");
    }


};
